//
//  QK.cpp
//  Chart
//
//  Created by CaoJun on 15/3/30.
//
//

#include "QKT.h"
#include "QKTSQLite.h"

using namespace ytx;
using namespace std;


QKT::QKT(IndexConfig indexConfig):IndexData(indexConfig, 0), requesLock(false)
{
    indexName = "QKT";
    type = QuotationType::QKT;
}

void QKT::callback(string tag, string data)
{
    YTXJson::Reader reader;
    YTXJson::Value value;
    
    try {
        if(reader.parse(data, value))
        {
            if ( this->kLineData != nil && tag == "QKTData"+this->kLineData->id) {
                requesLock = false;
                responseQKTData(value["datas"], value["info"]);
            }
        }
    } catch (void * __attribute__((annotate("oclint:suppress[unused local variable]"))) ex) {

    }
}

void QKT::onFail(string tag)
{
    requesLock = false;
}

void QKT::realCalculate(KLineData * data)
{
    indexData.clear();
    lineData.clear();
    
    if ( QKTData.size() == 0 || !data->hasData()) {
        return;
    }
    
    //先设置为灰色
    vector<double> qkData;
    
    //    vector<QKItem>::iterator qkItBegin = QKData.begin();
    vector<QKTItem>::iterator qkIt = QKTData.begin();
    vector<QKTItem>::iterator qkItEnd = QKTData.end();
    
    for (vector<KLineItem>::iterator kLineIt = data->kLineData.begin(); kLineIt != data->kLineData.end(); ++kLineIt) {
        KLineItem k = (*kLineIt);
        QKTItem qk = (*qkIt);
        int type = (int)QKTType::Flat;
        
        YTXTime datetime = k.dateTime;
        
        if (qk.tradedatenext > datetime && datetime+minutes(LineType::getRequestParamOfQuotationType(data->getQuotationType())) > qk.tradedatenext ) {
            datetime = qk.tradedatenext;
        }
        
        if ( qkIt != qkItEnd && qk.tradedatepre <= datetime ) {
            //在区间内 或者 如果是最后一条 就可以含了
            if (qk.tradedatenext > datetime || (qkIt == QKTData.end()-1 && qk.tradedatenext == datetime) ) {
                type = (int)qk.type;
                qkData.push_back(type);
            }
            else{
                //不在区间了qkIt++ kLineIt回退1重新算这根
                qkIt++;
                kLineIt--;
            }
        }
        else{
            qkData.push_back(type);
        }
        
    }
    
    indexData.push_back( qkData );
}


void QKT::calculate(Quotation * data)
{
    this->kLineData = (KLineData *)data;
    getQKTData();
    
}

void QKT::updateLastest(Quotation * data)
{
    calculate(data);
}

bool QKT::hasQKTData()
{
    return QKTData.size() > 0;
}

//调用时需要判断有没有QK
//getK已经有数据 或者 response 监听分时变化时也要判断
void QKT::getQKTData()
{
    if (!hasQKTData()) {
        QKTData = getQKTDataFromDB();
    }
    
    if (hasQKTData()) {
        if (!QKTDataIsEnough()) {
            string date = "";
            if (QKTData.size() != 0) {
                date =  QKTData.back().tradedatepre.toStringYYYYMMddHHmmss();
            }
            requestQKTData(date);
        }
        realCalculate(this->kLineData);
    }
    else {
        requestQKTData("");
    }
    
}

void QKT::requestQKTData(string date)
{
    if (requesLock) {
        return;
    }
    int type = LineType::getRequestParamOfQuotationTypeMinute(this->kLineData->quotationType);
    
    map<string, string> data;
    
    data.insert(make_pair("sid", ConvertToString(this->kLineData->id)));
    
    data.insert(make_pair("quotationType", ConvertToString(type)));
    
    if (date != "") {
        data.insert(make_pair("tradedate", date));
    }
    
    Config * config = Config::getInstance();
    
    string routing = config->communicate.qktdataRouting;
    
    DataOption dataOption = DataOption(data, routing);
    
    requesLock = true;
    requestData("QKTData"+this->kLineData->id, dataOption, "text/plain");
}

void QKT::responseQKTData(YTXJson::Value data, YTXJson::Value info)
{
    //加入到本地QKTData
    //存入到数据库
    int len = data.size();
    YTXTime tradedatepre, tradedatenext;
    if (len == 0) {
        if (hasQKTData()) {
            QKTItem & item = QKTData.back();
            tradedatenext = YTXTime( info["tradedatenext"].asString() );
            if (item.tradedatenext != tradedatenext) {
                item.tradedatenext = tradedatenext;
                updateQKTData(item);
                this->kLineData->fire("load", NULL);
            }
        }

        return;
    }
    
    
    YTXJson::Value item;
    YTXJson::Value itemNext;
    int type;
    vector<QKTItem> result;
    int index = 0;
    
    for (YTXJson::Value::iterator it = data.begin(); it != data.end(); ++it) {
        item = *it;
        
        type = item["type"].asInt();
        
        tradedatepre = YTXTime( item["tradedatepre"].asString() );
        
        //        NSLog("test:%s", item["tradedatepre"].asString().c_str());
        
        // itnext != data.end 有bug
        if ( index+1 < len ) {
            
            itemNext = data[index+1];
            tradedatenext = YTXTime( itemNext["tradedatepre"].asString() );
            
            //            CCLOG("test:%s", itemNext["tradedatepre"].asString().c_str() );
        }
        else{
            tradedatenext = YTXTime::not_a_date_time();
        }
        
        QKTItem qk = {
            tradedatepre,
            (QKTType::QKTType)type,
            tradedatenext,
        };
        index++;
        result.push_back(qk);
    }
    
    tradedatenext = YTXTime( info["tradedatenext"].asString() );
    
    //    NSLog("tradedatenext:%s", Tools::ptime2StringYYYYMMddHHmmss(tradedatenext).c_str());
    
    result.back().tradedatenext = tradedatenext;
    
    
    if (hasQKTData()) {
        //或者时间小于匹配
        if(QKTData.back().tradedatepre < result.front().tradedatepre){
            QKTItem & item = QKTData.back();
            item.tradedatenext =  result.front().tradedatepre;
            updateQKTData(item);
            QKTData.insert(QKTData.end(), result.begin(), result.end());
            saveQKTDataToDB(result);
        }
    }
    else {
        //没有数据
        QKTData = result;
        saveQKTDataToDB(result);
    }
    
    //发事件 出去重绘
     return this->kLineData->fire("load", NULL);
    
}

bool QKT::QKTDataIsEnough()
{
    if (!this->kLineData->hasData()) {
        return true;
    }
    
    if (!hasQKTData()) {
        return false;
    }
    
    //    CCLog("QKDataIsEnough: %s %s", Tools::ptime2StringYYYYMMddHHmmss(QKData.back().tradedatenext).c_str(), Tools::ptime2StringYYYYMMddHHmmss(QK.back().dateTime).c_str());
    
    return QKTData.back().tradedatenext >= this->kLineData->kLineData.back().dateTime;
}

bool QKT::saveQKTDataToDB(vector<QKTItem> ret)
{
    QKTSQLite sqlite;
    
    string tableName = sqlite.getTableName(this->kLineData);
    
    sqlite.createQKTDataTableIfNotExit(tableName);
    
    return sqlite.insertData(tableName, ret);
}

bool QKT::updateQKTData(QKTItem ret)
{
    QKTSQLite sqlite;
    
    string tableName = sqlite.getTableName(this->kLineData);
    
    sqlite.createQKTDataTableIfNotExit(tableName);
    
    return sqlite.updateData(tableName, ret);
    
}

vector<QKTItem> QKT::getQKTDataFromDB()
{
    vector<QKTItem> ret;
    
    QKTSQLite sqlite;
    
    string tableName = sqlite.getTableName(this->kLineData);
    
    sqlite.createQKTDataTableIfNotExit(tableName);
    
    sqlite.getDataFromDB(tableName, &ret);
    
    return ret;
}

void QKT::setQKTData(QKTItem qk)
{
    if (!hasQKTData()){
        return;
    }
    
    getQKTData();
    
}

void QKT::clearIfParentDataChanged(const Quotation * data)
{
    if (!isSameParentData(data)) {
        cleanData();
        requesLock = false;
    }
}

void QKT::cleanData()
{
    QKTData.clear();
    indexData.clear();
    lineData.clear();
}